package com.platform.modules.wallet.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.platform.common.constant.ApiConstant;
import com.platform.common.exception.BaseException;
import com.platform.common.utils.redis.RedisUtils;
import com.platform.common.web.service.impl.BaseServiceImpl;
import com.platform.modules.chat.domain.ChatGroup;
import com.platform.modules.chat.domain.ChatUser;
import com.platform.modules.chat.service.ChatGroupService;
import com.platform.modules.chat.service.ChatUserService;
import com.platform.modules.push.enums.PushMsgTypeEnum;
import com.platform.modules.push.service.ChatPushService;
import com.platform.modules.push.vo.PushParamVo;
import com.platform.modules.wallet.dao.WalletRedPacketSubDao;
import com.platform.modules.wallet.domain.WalletAccount;
import com.platform.modules.wallet.domain.WalletRedPacket;
import com.platform.modules.wallet.domain.WalletRedPacketSub;
import com.platform.modules.wallet.enums.*;
import com.platform.modules.wallet.service.WalletAccountService;
import com.platform.modules.wallet.service.WalletRedPacketService;
import com.platform.modules.wallet.service.WalletRedPacketSubService;
import com.platform.modules.wallet.service.WalletService;
import com.platform.modules.wallet.vo.AccountVo01;
import com.platform.modules.wallet.vo.RedPacketSubVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service("walletRedPacketSubService")
public class WalletRedPacketServiceSubImpl extends BaseServiceImpl<WalletRedPacketSub> implements WalletRedPacketSubService {

    @Autowired
    private RedisUtils redisUtils;
    @Resource
    private WalletService walletService;
    @Resource
    private WalletRedPacketSubDao walletRedPacketSubDao;
    @Resource
    private WalletAccountService walletAccountService;
    @Resource
    private WalletRedPacketService walletRedPacketService;
    @Resource
    private ChatPushService chatPushService;
    @Resource
    private ChatGroupService groupService;
    @Resource
    private ChatUserService chatUserService;

    @Autowired
    public void setBaseDao() {
        super.setBaseDao(walletRedPacketSubDao);
    }

    @Override
    public void createRedPacketSub(RedPacketSubVo vo) {

        WalletRedPacketSub bean = getBean();
        bean.setRedPacketId(vo.getRedpacketId());
        bean.setAmount(vo.getAmount());
        bean.setFromId(vo.getFromId());
        bean.setBestLuck(vo.getBestLuck());
        add(bean);
    }


    public List<WalletRedPacketSub> queryByRedRacketId(Long redPacketId) {

        return new WalletRedPacketSub().selectList(new LambdaQueryWrapper<WalletRedPacketSub>()
                .eq(WalletRedPacketSub::getRedPacketId, redPacketId)
                .eq(WalletRedPacketSub::getStatus, RedPacketStatusEnum.INIT));
    }


    public List<WalletRedPacketSub> queryByToId(Long redPacketId, Long toId) {

        return new WalletRedPacketSub().selectList(new LambdaQueryWrapper<WalletRedPacketSub>()
                .eq(WalletRedPacketSub::getRedPacketId, redPacketId)
                .eq(WalletRedPacketSub::getToId, toId));
    }

    @Override
    public List<WalletRedPacketSub> queryByStatus(Long redPacketId, RedPacketStatusEnum statusEnum) {

        return new WalletRedPacketSub().selectList(new LambdaQueryWrapper<WalletRedPacketSub>()
                .eq(WalletRedPacketSub::getRedPacketId, redPacketId)
                .eq(WalletRedPacketSub::getStatus, statusEnum));
    }

    @Override
    public List<WalletRedPacketSub> queryByStatusSuccess(Long redPacketId) {
        return queryByStatus(redPacketId, RedPacketStatusEnum.SUCCESS);
    }
    @Override
    public List<WalletRedPacketSub> queryByStatusInit(Long redPacketId) {
        return queryByStatus(redPacketId, RedPacketStatusEnum.INIT);
    }
    @Override
    public boolean openRedPacket(Long redPacketId, Long userId) {

        List<WalletRedPacketSub> walletRedPacketSubs = queryByToId(redPacketId, userId);
        if (walletRedPacketSubs.size() > 0) {
            throw new BaseException("该红包已经抢过了");
        }

        String key = ApiConstant.WALLET_RED_PACKET + redPacketId;
        String value = String.valueOf(userId);

        redisUtils.sAdd(key, value);
        redisUtils.expire(key, 5, TimeUnit.MINUTES);

        List<WalletRedPacketSub> list = this.queryByRedRacketId(redPacketId);

        for (WalletRedPacketSub walletRedPacketSub : list) {
            if (RedPacketSubStatusEnum.INIT.equals(walletRedPacketSub.getStatus())) {

                successOpen(walletRedPacketSub.getId(), userId);//完成收
                AccountVo01 accountVo = new AccountVo01();
                accountVo.setOtherId(walletRedPacketSub.getId());
                accountVo.setAmount(walletRedPacketSub.getAmount());
                accountVo.setType(AccountTypeEnum.RED_PACKET_IN);
                accountVo.setUserId(userId);

                WalletAccount account = walletAccountService.createRecord(accountVo);//创建账本记录
                walletAccountService.successRecord(account.getId());//完成账本记录
                walletService.add(accountVo.getAmount(), account.getUserId());//加余额
                successStatus(walletRedPacketSub.getId());//完成入
                walletRedPacketSub.setToId(userId);

                WalletRedPacket redPacket = walletRedPacketService.findById(redPacketId);
                if (RedPacketTypeEnum.SINGLE.equals(redPacket.getType())) {

                    ChatUser to = chatUserService.getById(walletRedPacketSub.getToId());
                    String content = StrUtil.format(ApiConstant.RED_PACKET_RECEIVE_NOTICE, to.getNickName());
                    // 发送通知
                    chatPushService.pushMsg(ChatUser.initParam(to)
                            .setContent(content).setToId(walletRedPacketSub.getFromId()), PushMsgTypeEnum.ALERT);

                    ChatUser from = chatUserService.getById(walletRedPacketSub.getFromId());
                    chatPushService.pushMsg(ChatUser.initParam(from).setContent(content).setToId(walletRedPacketSub.getToId()), PushMsgTypeEnum.ALERT);
                } else {

                    // 查询群组
                    ChatGroup group = groupService.getById(redPacket.getToId());

                    ChatUser to = chatUserService.getById(walletRedPacketSub.getToId());
                    String content = StrUtil.format(ApiConstant.RED_PACKET_RECEIVE_NOTICE, to.getNickName());
                    // 查询群列表
                    List<PushParamVo> userList = groupService.queryFriendPushFrom(redPacket.getToId(), content);
                    // 群信息
                    PushParamVo groupUser = new PushParamVo()
                            .setUserId(group.getId())
                            .setNickName(group.getName())
                            .setPortrait(group.getPortrait());
                    // 推送
                    chatPushService.pushMsg(userList, groupUser, PushMsgTypeEnum.RED_PACKET);
                }

                return true;
            }
        }

        return false;
    }

    @Override
    public List<WalletRedPacketSub> getRefun() {

        DateTime date = DateUtil.date();
        return new WalletRedPacketSub().selectList(new LambdaQueryWrapper<WalletRedPacketSub>()
                .eq(WalletRedPacketSub::getStatus, TransferStatusEnum.INIT)
                .eq(WalletRedPacketSub::getInStatus, TransferInEnum.INIT)
                .le(WalletRedPacketSub::getRefundableTime, date));
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void refund(Long id) {
        WalletRedPacketSub sub = findById(id);
        if (!RedPacketSubStatusEnum.INIT.equals(sub.getStatus())) {
            throw new BaseException("订单状态已完成收、入");
        }
        if (!RedPacketSubInEnum.INIT.equals(sub.getInStatus())) {
            throw new BaseException("订单状态接收已完成");
        }

        DateTime date = DateUtil.date();
        sub.setStatus(RedPacketSubStatusEnum.REFUND);
        sub.setRefundTime(date);
        sub.setUpdateTime(date);
        updateById(sub);


        AccountVo01 accountVo = new AccountVo01();
        accountVo.setOtherId(sub.getId());
        accountVo.setAmount(sub.getAmount());
        accountVo.setType(AccountTypeEnum.REFUND);
        accountVo.setUserId(sub.getFromId());

        WalletAccount account = walletAccountService.createRecord(accountVo);
        walletAccountService.successRecord(account.getId());//完成账本记录
        walletService.add(accountVo.getAmount(), account.getUserId());//加余额 完成入
    }

    /**
     * 完成接收红包
     *
     * @param id
     */
    private void successOpen(Long id, Long userId) {

        WalletRedPacketSub sub = findById(id);
        sub.setToId(userId);
        DateTime date = DateUtil.date();
        sub.setReceiveTime(date);
        sub.setUpdateTime(date);
        sub.setInStatus(RedPacketSubInEnum.SUCCESS);//完成收
        updateById(sub);
    }

    private void successStatus(Long id) {

        WalletRedPacketSub sub = findById(id);
        DateTime date = DateUtil.date();
        sub.setSuccessTime(date);
        sub.setUpdateTime(date);
        sub.setStatus(RedPacketSubStatusEnum.SUCCESS);
        updateById(sub);
    }

    private WalletRedPacketSub getBean() {
        DateTime date = DateUtil.date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(calendar.DATE, 1);//把日期往后增加一天.整数往后推,负数往前移动
        date = DateUtil.date(calendar.getTime()); //这个时间就是日期往后推一天的结果

        return new WalletRedPacketSub()
                .setStatus(RedPacketSubStatusEnum.INIT)
                .setInStatus(RedPacketSubInEnum.INIT)
                .setBestLuck(RedPacketLuckEnum.NO)
                .setCreateTime(DateUtil.date())
                .setRefundableTime(date);
    }
}
